/******************************************************************************
 * Include files
 ******************************************************************************/
#include <stdio.h>
#include "bsp_init.h"
#include "hc32_ll.h"
#include "hc32_ll_clk.h"
#include "hc32_ll_utility.h"
#include "hc32_ll_usart.h"
#include "uart.h"


/**
 * @brief  BSP clock initialize.
 *         SET board system clock to PLLH@240MHz
 *         Flash: 5 wait
 *         SRAM_HS: 1 wait
 *         SRAM1_2_3_4_B: 2 wait
 *         PCLK0: 240MHz
 *         PCLK1: 120MHz
 *         PCLK2: 60MHz
 *         PCLK3: 60MHz
 *         PCLK4: 120MHz
 *         EXCLK: 120MHz
 *         HCLK:  240MHz
 * @param  None
 * @retval None
 */
void BSP_CLK_Init(void)
{
  stc_clock_xtal_init_t stcXtalInit;
  stc_clock_pll_init_t stcPLLHInit;

  /* PCLK0, HCLK  Max 240MHz */
  /* PCLK1, PCLK4 Max 120MHz */
  /* PCLK2, PCLK3 Max 60MHz  */
  /* EX BUS Max 120MHz */
  CLK_SetClockDiv(CLK_BUS_CLK_ALL, \
                  (CLK_PCLK0_DIV1 | CLK_PCLK1_DIV2 | CLK_PCLK2_DIV4 | \
                   CLK_PCLK3_DIV4 | CLK_PCLK4_DIV2 | CLK_EXCLK_DIV2 | \
                   CLK_HCLK_DIV1));

  (void)CLK_XtalStructInit(&stcXtalInit);
  /* Config Xtal and enable Xtal */
  stcXtalInit.u8Mode   = CLK_XTAL_MD_OSC;
  stcXtalInit.u8Drv    = CLK_XTAL_DRV_ULOW;
  stcXtalInit.u8State  = CLK_XTAL_ON;
  stcXtalInit.u8StableTime = CLK_XTAL_STB_2MS;
  (void)CLK_XtalInit(&stcXtalInit);

  (void)CLK_PLLStructInit(&stcPLLHInit);
  /* VCO = (8/1)*120 = 960MHz*/
  stcPLLHInit.u8PLLState = CLK_PLL_ON;
  stcPLLHInit.PLLCFGR = 0UL;
  stcPLLHInit.PLLCFGR_f.PLLM = 1UL - 1UL;
  stcPLLHInit.PLLCFGR_f.PLLN = 50UL - 1UL;
  stcPLLHInit.PLLCFGR_f.PLLP = 2UL - 1UL;
  stcPLLHInit.PLLCFGR_f.PLLQ = 2UL - 1UL;
  stcPLLHInit.PLLCFGR_f.PLLR = 2UL - 1UL;
  stcPLLHInit.PLLCFGR_f.PLLSRC = CLK_PLL_SRC_XTAL;
  (void)CLK_PLLInit(&stcPLLHInit);

  /* Highspeed SRAM set to 0 Read/Write wait cycle */
  SRAM_SetWaitCycle(SRAM_SRAMH, SRAM_WAIT_CYCLE0, SRAM_WAIT_CYCLE0);

  /* SRAM1_2_3_4_backup set to 1 Read/Write wait cycle */
  SRAM_SetWaitCycle((SRAM_SRAM12 | SRAM_SRAM3 | SRAM_SRAMR), SRAM_WAIT_CYCLE1, SRAM_WAIT_CYCLE1);

  /* 0-wait @ 40MHz */
  (void)EFM_SetWaitCycle(EFM_WAIT_CYCLE5);

  /* 4 cycles for 200 */
  GPIO_SetReadWaitCycle(GPIO_RD_WAIT3);
  CLK_SetSysClockSrc(CLK_SYSCLK_SRC_PLL);
}

 


#if (defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)) || \
    (defined (__ICCARM__) && (__VER__ < 9000000)) || (defined (__CC_ARM))
/**
 * @brief  Re-target fputc function.
 * @param  [in] ch
 * @param  [in] f
 * @retval int32_t
 */
int32_t fputc(int32_t ch, FILE *f)
{
    (void)f;  /* Prevent unused argument compilation warning */

    return (LL_OK == Debug_Uart_SendDataPoll((char)ch)) ? ch : -1;
}

#elif (defined (__ICCARM__) && (__VER__ >= 9000000))

#include <LowLevelIOInterface.h>
#pragma module_name = "?__write"
size_t __dwrite(int handle, const unsigned char *buffer, size_t size)
{
    size_t nChars = 0;
    size_t i;

    if (buffer == NULL) {
        /*
         * This means that we should flush internal buffers.  Since we
         * don't we just return.  (Remember, "handle" == -1 means that all
         * handles should be flushed.)
         */
        return 0;
    }

    /* This template only writes to "standard out" and "standard err",
     * for all other file handles it returns failure. */
    if (handle != _LLIO_STDOUT && handle != _LLIO_STDERR) {
        return _LLIO_ERROR;
    }

    for (i = 0; i < size; i++) {
        if (Debug_Uart_SendDataPoll((char)buffer[i]) < 0) {
            return _LLIO_ERROR;
        }

        ++nChars;
    }

    return nChars;
}

#elif defined (__GNUC__) && !defined (__CC_ARM)

#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>

__attribute__((weak)) int _isatty(int fd)
{
  if (fd >= STDIN_FILENO && fd <= STDERR_FILENO)
    return 1;
  errno = EBADF;
    return 0;
}

__attribute__((weak)) int _close(int fd)
{
  if (fd >= STDIN_FILENO && fd <= STDERR_FILENO)
    return 0;
  errno = EBADF;
    return -1;
}

__attribute__((weak)) int _lseek(int fd, int ptr, int dir)
{
  (void)fd;
  (void)ptr;
  (void)dir;

  errno = EBADF;
  return -1;
}

__attribute__((weak)) int _fstat(int fd, struct stat *st)
{
  if (fd >= STDIN_FILENO && fd <= STDERR_FILENO)
  {
    st->st_mode = S_IFCHR;
    return 0;
  }
  errno = EBADF;
  return 0;
}

__attribute__((weak)) int _read(int file, char *ptr, int len)
{
  (void)file;
  int DataIdx;
  for (DataIdx = 0; DataIdx < len; DataIdx++)
  {
    ptr++ ;
  }
  return len;
}

__attribute__((weak)) void _getpid(void)
{
  ;
}

__attribute__((weak)) void _kill(void)
{
  ;
}
/**
 * @brief  Re-target _write function.
 * @param  [in] fd
 * @param  [in] data
 * @param  [in] size
 * @retval int32_t
 */
int32_t _write(int fd, char data[], int32_t size)
{
    int32_t i = -1;

    if (NULL != data) {
        (void)fd;  /* Prevent unused argument compilation warning */

        for (i = 0; i < size; i++) {
            if (LL_OK != Debug_Uart_SendDataPoll(data[i])) {
                break;
            }
        }
    }

    return i ? i : -1;
}

#endif


/******************************************************************************
 * EOF (not truncated)
 ******************************************************************************/
